package com.yixing.tech.entity.service;


import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.entity.po.EntityData;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;

/**
 * @author yixing tech
 * 实体处理钩子服务
 */
@Component
public abstract class AbstractEntityHookService implements EntityHookService {

    @Autowired
    private MongoTemplate mongoTemplate;

    protected abstract String getEntityId();

    @Override
    public void beforeDelete(String tableId, String dataId) throws BusinessException {
        // 删除约束
        // 查询本本条数据
        Document entitySchema = mongoTemplate.findOne(Query.query(Criteria.where("isDelete").ne(1)
                        .and("_id").is(new ObjectId(tableId))),
                Document.class, "obj");
        Document entityData = mongoTemplate.findOne(Query.query(Criteria.where("isDelete").ne(1).and("_id").is(new ObjectId(dataId))),
                Document.class, "entity_" + tableId);
        if (entityData != null && entitySchema != null) {
            List<Document> checkObjList = mongoTemplate.find(Query.query(Criteria.where("isDelete").ne(1)
                            .and("attrs.reference").is(tableId)),
                    Document.class, "obj");
            for (Document checkReference : checkObjList) {
                Document referenceAttr = checkReference.getList("attrs", Document.class).stream()
                        .filter(x -> Objects.equals(x.get("reference"), tableId) && Objects.equals(x.get("type"), "obj"))
                        .findFirst().orElse(null);
                if (referenceAttr != null) {
                    String relationalField = referenceAttr.getString("relationalField");
                    String attrCode = referenceAttr.getString("code");
                    String checkObjId = checkReference.getString("id");
                    long referenceCount = mongoTemplate.count(Query.query(Criteria.where("isDelete").ne(1).and(attrCode).is(entityData.get(relationalField))), "entity_" + checkObjId);
                    if (referenceCount > 0) {
                        throw new BusinessException(String.format("[%s]的数据被[%s]的数据引用，请先删除[%s]中相关数据再执行删除",
                                entitySchema.getString("name"), checkReference.getString("name"), checkReference.getString("name")));
                    }
                }
            }
        }
        doBeforeDelete(tableId, dataId);
    }

    protected void doBeforeDelete(String tableId, String dataId) {}

    @Override
    public EntityData beforeInsert(String tableId, EntityData data) throws BusinessException {
        return data;
    }

    @Override
    public EntityData afterInsert(String tableId, EntityData data) throws BusinessException {
        return data;
    }

    @Override
    public void afterDelete(String tableId, String entityId) throws BusinessException {

    }

    @Override
    public EntityData beforeUpdate(String tableId, EntityData data) throws BusinessException {
        return data;
    }

    @Override
    public EntityData afterUpdate(String tableId, EntityData oldData, EntityData newData) throws BusinessException {
        return newData;
    }
}
